#include <iostream>
#include <unistd.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#include "log.hpp"

#define SIZE 1024

// // 使用手册：当命令行输入不正确时，可提示正确使用信息
// void Usage(std::string proc)
// {
//     std::cout << "\nUsage:" << proc << " server_ip server_port\n"
//               << std::endl;
// }

// // 启动方式：udp_client server_ip server_port要知道服务端的端口号和IP地址
// int main(int argc, char **argv)
// {
//     // 1、检测命令行参数是否输入正确
//     if (argc != 3)
//     {
//         Usage(argv[0]);
//         exit(1);
//     }

//     // 2、创建套接字
//     int sock = socket(AF_INET, SOCK_DGRAM, 0);//这里是UDP通信
//     if (sock < 0) // 创建失败
//     {
//         std::cerr << "socket error" << std::endl;
//         exit(2);
//     }
//     logMessage(DEBUG, "socket succes. sock: %d", sock);

//     // 3、进行网络通信
//     // 3.1、通信前的准备：获取服务端的IP、端口号
//     struct sockaddr_in serveraddr;
//     bzero(&serveraddr, sizeof serveraddr);
//     serveraddr.sin_family = AF_INET;
//     serveraddr.sin_port = htons(atoi(argv[2])); // 要向服务器发送数据，要先经过网络，故这里存在字节序的转换(使用与server同)
//     serveraddr.sin_addr.s_addr = inet_addr(argv[1]);

//     // 3.2、循环式向服务端发出请求并接收响应结果
//     // PS:首次测试，演示字符型数据传递，echo服务器
//     while (true)
//     {
//         // a、向服务器发送请求
//         std::string message; // 将交付的信息数据
//         std::getline(std::cin, message);
//         if (message == "quit") // string类中有operator==,建议访问官网查阅
//             break;

//         sendto(sock, message.c_str(), message.size(), 0, (struct sockaddr *)&serveraddr, sizeof serveraddr);

//         // b、接收来自服务器的响应
//         char client_buffer[SIZE]; // 用于存储数据
//         struct sockaddr_in temp;  // 临时变量：用于recvfrom中参数(为保证该函数成功使用)
//         memset(&temp, 0, sizeof temp);
//         socklen_t len = sizeof temp;
//         ssize_t s = recvfrom(sock, client_buffer, sizeof client_buffer, 0, (struct sockaddr *)&temp, &len);
//         if (s > 0) // 接收到实际数据
//         {
//             client_buffer[s] = 0;
//             // echo版服务器，相关后续处理：打印到显示器表示服务端有确切地将数据通过网络sendto到客户端
//             std::cout << "server echo : " << client_buffer << std::endl;
//         }
//     }

//     return 0;
// }

void Usage(std::string proc)
{
    std::cout << "\nUsage: " << proc << "ip port" << std::endl;
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(1);
    }

    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        logMessage(ERROR, "%d:%s", errno, strerror(errno));
        exit(2);
    }
    logMessage(DEBUG, "创建套接字成功,sock:%d ", sock);

    struct sockaddr_in serveraddr;
    bzero(&serveraddr, sizeof serveraddr);
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(atoi(argv[2]));
    inet_aton(argv[1],&serveraddr.sin_addr);
    //serveraddr.sin_addr.s_addr = inet_addr(argv[1]);

    logMessage(DEBUG, "开始通信");
    while (true)
    {
        std::string message;
        std::getline(std::cin, message);
        if (message == "quit")
            break;
        sendto(sock, message.c_str(), message.size(), 0, (struct sockaddr *)&serveraddr, sizeof serveraddr);

        char client_buffer[SIZE];
        struct sockaddr_in temp;
        memset(&temp, 0, sizeof temp);
        socklen_t len = sizeof temp;
        ssize_t ret = recvfrom(sock, client_buffer, sizeof(client_buffer), 0, (struct sockaddr *)&temp, &len);
        if (len > 0)
        {
            client_buffer[len] = 0;
            std::cout << "server echo: " << client_buffer << std::endl;
        }
    }
    return 0;
}